package Domain;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * The dropbox server
 * 
 * @author kenneth
 */
public class DropboxServer implements Runnable {
    
    private static final int PORT_NUMBER = 1337;
    private ServerSocket serverSocket;
    private boolean run;
    private ExecutorService threadExecutor;
    private final Serverlog serverlog;
    
    /**
     * Constructor
     *
     * @param serverlog The server log, can be used to send messages to the server info area.
     */
    public DropboxServer(Serverlog serverlog) {
        this.serverlog = serverlog;
    }
    
    @Override
    public void run() {
        this.startServer();
    }
    
    /**
     * Starts the server. <br />
     * This will open a new client connection when a new client tries to connect to the server. <br />
     * All client connections are added to a cached thread pool.
     */
    private void startServer() {
        serverlog.addMessage("The server is going to start...");
        serverlog.addMessage("Trying to open the port...");
        try {
            serverSocket = new ServerSocket(PORT_NUMBER);
            serverlog.addMessage("Port has been opened");
        } catch(Exception e) {
            serverlog.addMessage(e.getMessage());
            serverlog.addMessage("Server stopped");
            return;
        }
        run = true;
        threadExecutor = Executors.newCachedThreadPool();
        while(run) {
            serverlog.addMessage("Waiting for connection");
            try {
                Socket client = serverSocket.accept();
                serverlog.addMessage("A new connection has been opened");
                ClientConnection clientConnection = new ClientConnection(client,serverlog);
                threadExecutor.execute(clientConnection);
                
            } catch (IOException ex) {
                if(run == true) {
                    serverlog.addMessage("Failed to initialize a connection");
                }
            }
        }
    }
    
    /**
     * Stops the server.
     */
    public void stopServer() {
        threadExecutor.shutdownNow();
        serverlog.addMessage("Client connections have shutdown");
        serverlog.addMessage("Trying to close the port");
        try {
            serverSocket.close();
            run = false;
        } catch (IOException ex) {
            serverlog.addMessage("Failed to close the port");
            return;
        }
        serverlog.addMessage("Port closed");
        serverlog.addMessage("Server stopped");
    }

    /**
     * Checks whether the server is running or not.
     *
     * @return True when the server is running.
     */
    public boolean isRunning() {
        return run;
    }
    
}
